package initialize

import (
	"flag"
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/go-kratos/kratos/v2/config"
	"github.com/go-kratos/kratos/v2/config/file"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/jiushengTech/common/utils/idutil"
	"github.com/jiushengTech/common/utils/pathutil"
	"github.com/redis/go-redis/v9"
	"github.com/spf13/viper"
	"path/filepath"
	"transfer-service/internal/conf"
	"transfer-service/internal/global"
)

var flagBaseConf string //默认必读配置文件

func InitAll() {
	// 初始化本地配置
	initConfigBind()
	// 初始化zap日志
	InitZap(global.BC.GetInfra().GetLog().GetZap())
	// 初始化redis
	//InitRedisClient(global.BC.GetData().GetRedis())
	// 初始化雪花
	InitSnowflake()
	//初始化协程池
	InitAnts(global.BC.GetInfra().GetAnts())
	// 初始化mqtt
	InitMQTTClient(global.BC)
	// 初始化Msql
	//InitMysql(global.BC)

	// 初始化viper
	//InitViper()
}

func initLocalConfig() {
	currentPath := pathutil.GetCurrentPath()
	configPath := filepath.Join(currentPath, "../../configs/config.yaml")
	flag.StringVar(&flagBaseConf, "conf", configPath, "config path, eg: -conf config.yaml")
	flag.Parse()
	c := config.New(
		config.WithSource(
			file.NewSource(flagBaseConf),
		),
	)
	if err := c.Load(); err != nil {
		panic(err)
	}
	var lc conf.LocalConfig
	if err := c.Scan(&lc); err != nil {
		panic(err)
	}
	global.LC = &lc
}

func InitSnowflake() {
	idutil.InitSnowflake()
}

func initConfigBind() {
	var configDir string // 所有配置文件的目录
	var confs []string   //需加载额外配置文件
	var bizConf string   //业务配置
	currentPath := pathutil.GetCurrentPath()
	configPath := filepath.Join(currentPath, "../../configs/config.yaml")
	flag.StringVar(&flagBaseConf, "conf", configPath, "config path, eg: -conf config.yaml")
	flag.Parse()
	configDir = filepath.Join(flagBaseConf, "../")
	confs = append(confs, flagBaseConf)
	c := config.New(
		config.WithSource(
			file.NewSource(flagBaseConf),
		),
	)
	if err := c.Load(); err != nil {
		panic(err)
	}
	var bc conf.Bootstrap
	if err := c.Scan(&bc); err != nil {
		panic(err)
	}
	switch bc.Profiles.Env {
	case "dev":
		bizConf = filepath.Join(configDir, "config-dev.yaml")
	case "prod":
		bizConf = filepath.Join(configDir, "config-prod.yaml")
	case "gray":
		bizConf = filepath.Join(configDir, "config-gray.yaml")
	default:
		configName := "config-" + bc.Profiles.Env + ".yaml"
		bizConf = filepath.Join(configDir, configName)
	}
	if &bizConf != nil {
		confs = append(confs, bizConf)
	}
	var sources []config.Source
	for _, confPath := range confs {
		source := file.NewSource(confPath)
		sources = append(sources, source)
	}

	c = config.New(config.WithSource(sources...))
	if err := c.Load(); err != nil {
		panic(err)
	}
	defer func(c config.Config) {
		err := c.Close()
		if err != nil {
			panic(err)
		}
	}(c)
	scan(c)
}

// 映射所有的配置文件
func scan(c config.Config) {
	var bc conf.Bootstrap
	if err := c.Scan(&bc); err != nil {
		panic(err)
	}
	global.BC = &bc
}

func InitRedisClient(conf *conf.Data_Redis) {
	global.REDIS = redis.NewClient(&redis.Options{
		Addr:         conf.Addr,
		Password:     conf.Password,
		DB:           int(conf.GetDb()),
		DialTimeout:  conf.GetDialTimeout().AsDuration(),
		WriteTimeout: conf.GetWriteTimeout().AsDuration(),
		ReadTimeout:  conf.GetReadTimeout().AsDuration(),
	})
}

func InitViper() {
	var confs []string //需加载额外配置文件
	currentPath := pathutil.GetCurrentPath()
	configPath := filepath.Join(currentPath, "../../configs/config.yaml")
	var configDir string // 所有配置文件的目录
	configDir = filepath.Join(configPath, "../")
	confs = append(confs, configPath)
	v := viper.New()
	v.SetConfigFile(configPath)
	err := v.ReadInConfig()
	value := v.GetString("profiles.env")
	switch value {
	case "dev":
		v.SetConfigFile(filepath.Join(configDir, "config-dev.yaml"))
	case "prod":
		v.SetConfigFile(filepath.Join(configDir, "config-prod.yaml"))
	case "gray":
		v.SetConfigFile(filepath.Join(configDir, "config-gray.yaml"))
	default:
		configName := "config-" + "prod" + ".yaml"
		v.SetConfigFile(filepath.Join(configDir, configName))
	}

	err = v.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("Fatal error config file: %s \n", err))
	}

	v.WatchConfig()
	v.OnConfigChange(func(e fsnotify.Event) {
		log.Info("config file changed:", e.Name)

		// 重新读取配置文件
		err := v.ReadInConfig()
		if err != nil {
			log.Info("Error reloading config:", err)
		}

		// 更新 global.VP
		global.VP = v
	})

	// 初始化时设置 global.VP
	global.VP = v
}
